import { message, notification } from 'antd';

/**
 * 错误类型枚举
 */
export const ErrorTypes = {
  NETWORK_ERROR: 'NETWORK_ERROR',
  API_ERROR: 'API_ERROR',
  VALIDATION_ERROR: 'VALIDATION_ERROR',
  TIMEOUT_ERROR: 'TIMEOUT_ERROR',
  BUSINESS_ERROR: 'BUSINESS_ERROR',
  UNKNOWN_ERROR: 'UNKNOWN_ERROR',
};

/**
 * 错误处理器配置
 */
class ErrorHandler {
  constructor() {
    this.errorMap = new Map();
    this.retryConfig = {
      maxRetries: 3,
      retryDelay: 1000,
      exponentialBackoff: true,
    };
  }

  /**
   * 分类错误类型
   * @param {Error} error - 错误对象
   * @returns {string} 错误类型
   */
  classifyError(error) {
    if (!error.response) {
      if (error.code === 'ECONNABORTED') {
        return ErrorTypes.TIMEOUT_ERROR;
      }
      if (error.message === 'Network Error') {
        return ErrorTypes.NETWORK_ERROR;
      }
      return ErrorTypes.UNKNOWN_ERROR;
    }

    const { status, data } = error.response;

    switch (status) {
      case 400:
        return ErrorTypes.VALIDATION_ERROR;
      case 401:
        return ErrorTypes.AUTH_ERROR;
      case 403:
        return ErrorTypes.BUSINESS_ERROR;
      case 404:
        return ErrorTypes.API_ERROR;
      case 429:
        return ErrorTypes.RATE_LIMIT_ERROR;
      case 500:
      case 502:
      case 503:
        return ErrorTypes.API_ERROR;
      default:
        return ErrorTypes.UNKNOWN_ERROR;
    }
  }

  /**
   * 获取用户友好的错误消息
   * @param {Error} error - 错误对象
   * @param {string} context - 上下文信息
   * @returns {string} 错误消息
   */
  getUserFriendlyMessage(error, context = '') {
    const errorType = this.classifyError(error);
    const messages = {
      [ErrorTypes.NETWORK_ERROR]: '网络连接失败，请检查网络后重试',
      [ErrorTypes.TIMEOUT_ERROR]: '请求超时，请稍后重试',
      [ErrorTypes.VALIDATION_ERROR]: '输入参数有误，请检查后重试',
      [ErrorTypes.BUSINESS_ERROR]: '操作失败：权限不足',
      [ErrorTypes.API_ERROR]: '服务器繁忙，请稍后重试',
      [ErrorTypes.AUTH_ERROR]: '登录已过期，请重新登录',
      [ErrorTypes.RATE_LIMIT_ERROR]: '请求过于频繁，请稍后重试',
      [ErrorTypes.UNKNOWN_ERROR]: '操作失败，请稍后重试',
    };

    // 优先使用服务器返回的错误消息
    if (error.response?.data?.message) {
      return error.response.data.message;
    }

    return messages[errorType] || messages[ErrorTypes.UNKNOWN_ERROR];
  }

  /**
   * 显示错误通知
   * @param {Error} error - 错误对象
   * @param {object} options - 显示选项
   */
  showError(error, options = {}) {
    const {
      message: customMessage,
      duration = 4.5,
      placement = 'topRight',
      type = 'error',
    } = options;

    const errorMessage = customMessage || this.getUserFriendlyMessage(error);

    if (type === 'notification') {
      notification.error({
        message: '操作失败',
        description: errorMessage,
        duration,
        placement,
      });
    } else {
      message.error(errorMessage, duration);
    }
  }

  /**
   * 记录错误日志
   * @param {Error} error - 错误对象
   * @param {object} context - 上下文信息
   */
  logError(error, context = {}) {
    const errorInfo = {
      type: this.classifyError(error),
      message: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString(),
      context,
      userAgent: navigator.userAgent,
      url: window.location.href,
    };

    console.error('Error occurred:', errorInfo);

    // 发送到错误监控服务
    if (process.env.NODE_ENV === 'production') {
      this.sendToMonitoring(errorInfo);
    }
  }

  /**
   * 发送到错误监控服务
   * @param {object} errorInfo - 错误信息
   */
  sendToMonitoring(errorInfo) {
    // 这里可以集成错误监控服务，如 Sentry
    if (window.Sentry) {
      window.Sentry.captureException(new Error(errorInfo.message), {
        extra: errorInfo,
      });
    }
  }

  /**
   * 判断错误是否可以重试
   * @param {Error} error - 错误对象
   * @returns {boolean} 是否可以重试
   */
  canRetry(error) {
    const errorType = this.classifyError(error);
    const retryableTypes = [
      ErrorTypes.NETWORK_ERROR,
      ErrorTypes.TIMEOUT_ERROR,
      ErrorTypes.API_ERROR,
    ];
    
    return retryableTypes.includes(errorType);
  }

  /**
   * 计算重试延迟
   * @param {number} attempt - 重试次数
   * @returns {number} 延迟时间（毫秒）
   */
  calculateRetryDelay(attempt) {
    const { retryDelay, exponentialBackoff } = this.retryConfig;
    
    if (exponentialBackoff) {
      return retryDelay * Math.pow(2, attempt - 1);
    }
    
    return retryDelay;
  }

  /**
   * 创建重试策略
   * @param {Function} operation - 要重试的操作
   * @param {object} options - 重试配置
   * @returns {Promise} 操作结果
   */
  async retry(operation, options = {}) {
    const {
      maxRetries = this.retryConfig.maxRetries,
      onRetry = () => {},
      onError = () => {},
    } = options;

    let lastError;

    for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
      try {
        return await operation();
      } catch (error) {
        lastError = error;

        if (attempt <= maxRetries && this.canRetry(error)) {
          const delay = this.calculateRetryDelay(attempt);
          
          onRetry({
            attempt,
            maxRetries,
            delay,
            error,
          });

          await this.sleep(delay);
          continue;
        }

        onError({
          attempt,
          maxRetries,
          error,
          canRetry: this.canRetry(error),
        });

        throw error;
      }
    }

    throw lastError;
  }

  /**
   * 休眠函数
   * @param {number} ms - 毫秒数
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 创建API包装器，自动处理错误和重试
   * @param {Function} apiCall - API调用函数
   * @param {object} options - 配置选项
   * @returns {Function} 包装后的API调用
   */
  createApiWrapper(apiCall, options = {}) {
    const {
      showError = true,
      showSuccess = false,
      successMessage = '操作成功',
      retryConfig = {},
      onError = () => {},
      onSuccess = () => {},
    } = options;

    return async (...args) => {
      try {
        const result = await this.retry(
          () => apiCall(...args),
          retryConfig
        );

        if (showSuccess && successMessage) {
          message.success(successMessage);
        }

        onSuccess(result);
        return result;
      } catch (error) {
        this.logError(error, { apiCall: apiCall.name, args });
        onError(error);

        if (showError) {
          this.showError(error);
        }

        throw error;
      }
    };
  }
}

// 创建单例实例
export const errorHandler = new ErrorHandler();

/**
 * 错误边界组件
 */
export class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, errorInfo) {
    errorHandler.logError(error, { component: 'ErrorBoundary', errorInfo });
  }

  render() {
    if (this.state.hasError) {
      return (
        <div style={{ padding: '20px', textAlign: 'center' }}>
          <h2>抱歉，发生了错误</h2>
          <p>{errorHandler.getUserFriendlyMessage(this.state.error)}</p>
          <button
            onClick={() => {
              this.setState({ hasError: false, error: null });
              if (this.props.onReset) {
                this.props.onReset();
              }
            }}
          >
            重新加载
          </button>
        </div>
      );
    }

    return this.props.children;
  }
}

/**
 * 使用错误处理的Hook
 * @param {object} options - 配置选项
 */
export const useErrorHandler = (options = {}) => {
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(false);

  const handleError = useCallback((error) => {
    setError(error);
    errorHandler.logError(error, options);
  }, [options]);

  const clearError = useCallback(() => {
    setError(null);
  }, []);

  const execute = useCallback(async (operation, operationOptions = {}) => {
    setIsLoading(true);
    setError(null);

    try {
      const result = await errorHandler.createApiWrapper(operation, {
        ...options,
        ...operationOptions,
      })();

      return result;
    } catch (error) {
      handleError(error);
      throw error;
    } finally {
      setIsLoading(false);
    }
  }, [options, handleError]);

  return {
    error,
    isLoading,
    execute,
    clearError,
  };
};

/**
 * 全局错误处理器
 */
export const setupGlobalErrorHandler = () => {
  // 捕获未处理的Promise拒绝
  window.addEventListener('unhandledrejection', (event) => {
    errorHandler.logError(event.reason, { source: 'unhandledrejection' });
    event.preventDefault();
  });

  // 捕获全局错误
  window.addEventListener('error', (event) => {
    errorHandler.logError(event.error, { 
      source: 'global', 
      filename: event.filename,
      lineno: event.lineno,
      colno: event.colno,
    });
    event.preventDefault();
  });
};